#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
情绪识别工具类
支持多种情绪识别方案：SnowNLP、关键词匹配、emoji识别
"""

import re
import json
from typing import Dict, List, Tuple, Optional
from snownlp import SnowNLP
import logging

TAG = __name__
logger = logging.getLogger(TAG)

class EmotionAnalyzer:
    """情绪识别分析器"""
    
    def __init__(self):
        # 七种基础情绪关键词词典（增强版 - 支持中英文）
        self.emotion_keywords = {
            "happy": [
                # 中文关键词
                "开心", "高兴", "快乐", "兴奋", "满意", "喜欢", "爱", "棒", "好", "赞", "不错", 
                "太好了", "太棒了", "完美", "优秀", "精彩", "美妙", "幸福", "愉快", "轻松",
                "哈哈", "嘿嘿", "呵呵", "嘻嘻", "心情好", "心情很好", "很快乐", "很满意",
                # 英文关键词
                "happy", "glad", "joy", "excited", "pleased", "satisfied", "love", "great", "good", "nice", "wonderful",
                "amazing", "perfect", "excellent", "fantastic", "beautiful", "delighted", "cheerful", "laugh", "smile",
                "😊", "😄", "😆", "😂", "🤣", "😍", "🥰", "🙂", "😉", "😎"
            ],
            "sad": [
                # 中文关键词
                "难过", "伤心", "痛苦", "失望", "沮丧", "郁闷", "心情不好", "心情低落", "很沮丧",
                "很失望", "很伤心", "很痛苦",
                # 英文关键词
                "sad", "sorrow", "pain", "disappointed", "depressed", "upset", "unhappy", "gloomy", "melancholy",
                "😢", "😭", "😔", "💔", "🥺"
            ],
            "angry": [
                # 中文关键词
                "愤怒", "生气", "讨厌", "恨", "烦", "糟糕", "差", "坏", "烂", "烦人", "气死",
                "很生气", "很愤怒", "气死我了", "太讨厌", "太糟糕",
                # 英文关键词
                "angry", "mad", "furious", "annoyed", "irritated", "hate", "bad", "terrible", "awful", "upset",
                "😠", "😡", "😤", "🤬"
            ],
            "fear": [
                # 中文关键词
                "害怕", "恐惧", "紧张", "担心", "焦虑", "压力", "恐怖", "吓人", "很害怕", "很恐惧",
                "很紧张", "很担心", "感到恐惧", "感到害怕",
                # 英文关键词
                "afraid", "scared", "fear", "worried", "anxious", "nervous", "terrified", "frightened", "panic",
                "😨", "😰", "😱", "😳"
            ],
            "surprise": [
                # 中文关键词
                "惊讶", "惊奇", "意外", "震惊", "没想到", "居然", "太意外", "很惊讶", "很震惊",
                # 英文关键词
                "surprised", "amazed", "shocked", "astonished", "unexpected", "wow", "incredible", "unbelievable",
                "😲", "😮", "🤯", "😯"
            ],
            "disgust": [
                # 中文关键词
                "恶心", "厌恶", "反感", "讨厌", "嫌弃", "太恶心", "很恶心", "很厌恶", "很反感",
                # 英文关键词
                "disgusted", "disgusting", "gross", "nasty", "revolting", "sick", "yuck", "eww",
                "🤢", "🤮", "😒", "🙄"
            ],
            "neutral": [
                # 中文关键词
                "嗯", "哦", "啊", "额", "呃", "好吧", "好的", "知道了", "明白", "了解",
                "一般", "还行", "可以", "随便", "无所谓", "一般般", "还可以",
                # 英文关键词
                "ok", "okay", "fine", "alright", "sure", "yes", "no", "maybe", "perhaps", "whatever",
                "😐", "😶", "🤔", "😌"
            ]
        }
        
        # emoji情绪映射（七种基础情绪）
        self.emoji_emotion_map = {
            # Happy 开心
            "😊": "happy", "😄": "happy", "😆": "happy", "😂": "happy", "🤣": "happy", 
            "😍": "happy", "🥰": "happy", "🙂": "happy", "😉": "happy", "😎": "happy",
            
            # Sad 难过
            "😢": "sad", "😭": "sad", "😔": "sad", "💔": "sad", "🥺": "sad",
            
            # Angry 愤怒
            "😠": "angry", "😡": "angry", "😤": "angry", "🤬": "angry",
            
            # Fear 恐惧
            "😨": "fear", "😰": "fear", "😱": "fear", "😳": "fear",
            
            # Surprise 惊讶
            "😲": "surprise", "😮": "surprise", "🤯": "surprise", "😯": "surprise",
            
            # Disgust 厌恶
            "🤢": "disgust", "🤮": "disgust", "😒": "disgust", "🙄": "disgust",
            
            # Neutral 中性
            "😐": "neutral", "😶": "neutral", "🤔": "neutral", "😌": "neutral"
        }
        
        # 情绪强度权重（七种基础情绪）
        self.emotion_weights = {
            "strong_happy": ["太棒了", "完美", "优秀", "精彩", "美妙", "幸福", "😂", "😍", "🥰"],
            "strong_sad": ["痛苦", "绝望", "崩溃", "😭", "💔"],
            "strong_angry": ["气死", "愤怒", "暴怒", "😠", "😡", "🤬"],
            "strong_fear": ["恐怖", "吓死", "害怕极了", "😱"],
            "strong_surprise": ["震惊", "太意外了", "🤯"],
            "strong_disgust": ["恶心死了", "太恶心", "🤮"],
            
            "medium_happy": ["开心", "高兴", "快乐", "满意", "喜欢", "😊", "😄", "😆"],
            "medium_sad": ["难过", "伤心", "失望", "沮丧", "😢", "😔"],
            "medium_angry": ["生气", "讨厌", "烦人", "😤"],
            "medium_fear": ["害怕", "恐惧", "紧张", "担心", "😨", "😰"],
            "medium_surprise": ["惊讶", "惊奇", "意外", "😲", "😮"],
            "medium_disgust": ["恶心", "厌恶", "反感", "🤢"],
            
            "weak_happy": ["好", "棒", "不错", "🙂"],
            "weak_sad": ["有点难过", "😔"],
            "weak_angry": ["有点生气", "😒"],
            "weak_fear": ["有点担心", "😳"],
            "weak_surprise": ["有点意外", "😯"],
            "weak_disgust": ["有点恶心", "🙄"],
            
            "neutral": ["嗯", "哦", "啊", "一般", "还行", "😶", "🤔"]
        }

    def analyze_emotion_snownlp(self, text: str) -> Dict[str, float]:
        """
        使用SnowNLP进行情绪分析
        
        Args:
            text: 待分析的文本
            
        Returns:
            包含情绪分析结果的字典
        """
        try:
            # 清理文本
            clean_text = self._clean_text(text)
            if not clean_text.strip():
                return {"neutral": 1.0, "confidence": 0.0}
            
            # 使用SnowNLP进行情感分析
            s = SnowNLP(clean_text)
            sentiment_score = s.sentiments  # 0-1之间，越接近1越积极
            
            # 转换为七种基础情绪分类（优化版3.0）
            # 更精确的阈值划分，提高准确率
            if sentiment_score > 0.8:
                emotion = "happy"
                confidence = sentiment_score
            elif sentiment_score > 0.65:
                emotion = "surprise"  # 积极但程度较低
                confidence = sentiment_score
            elif sentiment_score < 0.15:
                emotion = "disgust"  # 极度消极
                confidence = 1 - sentiment_score
            elif sentiment_score < 0.25:
                emotion = "angry"    # 很消极
                confidence = 1 - sentiment_score
            elif sentiment_score < 0.35:
                emotion = "sad"      # 消极
                confidence = 1 - sentiment_score
            elif sentiment_score < 0.45:
                emotion = "fear"     # 轻微消极
                confidence = 1 - sentiment_score
            elif sentiment_score < 0.55:
                emotion = "neutral" # 接近中性
                confidence = 1 - abs(sentiment_score - 0.5) * 2
            else:
                emotion = "neutral" # 中等积极，归为中性
                confidence = abs(sentiment_score - 0.5) * 2
            
            return {
                "emotion": emotion,
                "confidence": confidence,
                "sentiment_score": sentiment_score,
                "method": "snownlp"
            }
            
        except Exception as e:
            logger.error(f"SnowNLP情绪分析失败: {e}")
            return {"neutral": 1.0, "confidence": 0.0, "error": str(e)}

    def analyze_emotion_keywords(self, text: str) -> Dict[str, float]:
        """
        基于关键词的情绪分析
        
        Args:
            text: 待分析的文本
            
        Returns:
            包含情绪分析结果的字典
        """
        try:
            clean_text = self._clean_text(text)
            if not clean_text.strip():
                return {"neutral": 1.0, "confidence": 0.0}
            
            # 统计各类情绪关键词出现次数（增强版）
            emotion_scores = {"happy": 0, "sad": 0, "angry": 0, "fear": 0, "surprise": 0, "disgust": 0, "neutral": 0}
            
            # 增强关键词匹配：考虑词频和权重
            for emotion, keywords in self.emotion_keywords.items():
                for keyword in keywords:
                    count = clean_text.count(keyword)
                    if count > 0:
                        # 根据关键词长度和重要性给予不同权重
                        if len(keyword) >= 3:  # 长关键词权重更高
                            weight = 2.0
                        elif len(keyword) == 2:  # 中等长度
                            weight = 1.5
                        else:  # 短关键词
                            weight = 1.0
                        
                        # 重复出现的关键词增加权重
                        emotion_scores[emotion] += count * weight
            
            # 计算情绪强度
            total_score = sum(emotion_scores.values())
            if total_score == 0:
                return {"neutral": 1.0, "confidence": 0.0}
            
            # 归一化
            for emotion in emotion_scores:
                emotion_scores[emotion] = emotion_scores[emotion] / total_score
            
            # 确定主要情绪
            main_emotion = max(emotion_scores, key=emotion_scores.get)
            confidence = emotion_scores[main_emotion]
            
            return {
                "emotion": main_emotion,
                "confidence": confidence,
                "scores": emotion_scores,
                "method": "keywords"
            }
            
        except Exception as e:
            logger.error(f"关键词情绪分析失败: {e}")
            return {"neutral": 1.0, "confidence": 0.0, "error": str(e)}

    def analyze_emotion_emoji(self, text: str) -> Dict[str, any]:
        """
        基于emoji的情绪分析
        
        Args:
            text: 待分析的文本
            
        Returns:
            包含情绪分析结果的字典
        """
        try:
            emotions_found = []
            
            # 查找文本中的emoji
            for emoji, emotion in self.emoji_emotion_map.items():
                if emoji in text:
                    emotions_found.append({
                        "emoji": emoji,
                        "emotion": emotion,
                        "count": text.count(emoji)
                    })
            
            if not emotions_found:
                return {"neutral": 1.0, "confidence": 0.0, "method": "emoji"}
            
            # 选择出现次数最多的emoji对应的情绪
            main_emotion_info = max(emotions_found, key=lambda x: x["count"])
            
            return {
                "emotion": main_emotion_info["emotion"],
                "emoji": main_emotion_info["emoji"],
                "confidence": min(1.0, main_emotion_info["count"] * 0.3),  # 基于出现次数计算置信度
                "all_emotions": emotions_found,
                "method": "emoji"
            }
            
        except Exception as e:
            logger.error(f"Emoji情绪分析失败: {e}")
            return {"neutral": 1.0, "confidence": 0.0, "error": str(e)}

    def analyze_emotion_combined(self, text: str) -> Dict[str, any]:
        """
        综合多种方法的情绪分析
        
        Args:
            text: 待分析的文本
            
        Returns:
            综合的情绪分析结果
        """
        try:
            # 获取各种方法的分析结果
            snownlp_result = self.analyze_emotion_snownlp(text)
            keyword_result = self.analyze_emotion_keywords(text)
            emoji_result = self.analyze_emotion_emoji(text)
            
            # 权重设置（优化版）
            weights = {
                "snownlp": 0.2,    # 进一步降低SnowNLP权重
                "keywords": 0.6,   # 进一步提高关键词权重
                "emoji": 0.2       # 保持emoji权重
            }
            
            # 七种基础情绪映射
            emotion_mapping = {
                "happy": ["happy", "laughing", "loving", "excited"],
                "sad": ["sad", "crying", "depressed"],
                "angry": ["angry", "frustrated", "mad"],
                "fear": ["fear", "scared", "anxious"],
                "surprise": ["surprise", "shocked", "amazed"],
                "disgust": ["disgust", "disgusted", "revolted"],
                "neutral": ["neutral", "thinking", "confused"]
            }
            
            # 计算综合得分
            combined_scores = {"happy": 0, "sad": 0, "angry": 0, "fear": 0, "surprise": 0, "disgust": 0, "neutral": 0}
            
            # SnowNLP结果
            snownlp_emotion = snownlp_result.get("emotion", "neutral")
            if snownlp_emotion in combined_scores:
                combined_scores[snownlp_emotion] += weights["snownlp"] * snownlp_result.get("confidence", 0)
            
            # 关键词结果
            keyword_emotion = keyword_result.get("emotion", "neutral")
            if keyword_emotion in combined_scores:
                combined_scores[keyword_emotion] += weights["keywords"] * keyword_result.get("confidence", 0)
            
            # Emoji结果
            emoji_emotion = emoji_result.get("emotion", "neutral")
            if emoji_emotion in combined_scores:
                combined_scores[emoji_emotion] += weights["emoji"] * emoji_result.get("confidence", 0)
            
            # 智能情绪修正机制
            # 如果关键词有明确匹配且置信度较高，优先使用关键词结果
            keyword_confidence = keyword_result.get("confidence", 0)
            if keyword_confidence > 0.2:  # 降低阈值，更容易触发修正
                keyword_emotion = keyword_result.get("emotion", "neutral")
                if keyword_emotion in combined_scores:
                    # 给关键词结果额外加权
                    combined_scores[keyword_emotion] += 0.3  # 增加额外权重
            
            # 确定最终情绪
            final_emotion = max(combined_scores, key=combined_scores.get)
            final_confidence = combined_scores[final_emotion]
            
            # 如果最高分太低，默认为neutral
            if final_confidence < 0.1:
                final_emotion = "neutral"
                final_confidence = 0.5
            
            return {
                "emotion": final_emotion,
                "confidence": final_confidence,
                "scores": combined_scores,
                "details": {
                    "snownlp": snownlp_result,
                    "keywords": keyword_result,
                    "emoji": emoji_result
                },
                "method": "combined"
            }
            
        except Exception as e:
            logger.error(f"综合情绪分析失败: {e}")
            return {"neutral": 1.0, "confidence": 0.0, "error": str(e)}

    def analyze_chat_history(self, chat_history: List[Dict]) -> Dict[str, any]:
        """
        分析整个聊天记录的情绪趋势
        
        Args:
            chat_history: 聊天记录列表
            
        Returns:
            聊天记录的情绪分析结果
        """
        try:
            user_messages = []
            agent_messages = []
            
            # 分离用户和智能体的消息
            for message in chat_history:
                if message.get("chatType") == 1:  # 用户消息
                    user_messages.append(message.get("content", ""))
                else:  # 智能体消息
                    agent_messages.append(message.get("content", ""))
            
            # 分析用户情绪
            user_emotions = []
            for msg in user_messages:
                emotion_result = self.analyze_emotion_combined(msg)
                user_emotions.append(emotion_result)
            
            # 分析智能体情绪
            agent_emotions = []
            for msg in agent_messages:
                emotion_result = self.analyze_emotion_combined(msg)
                agent_emotions.append(emotion_result)
            
            # 计算整体情绪趋势
            overall_user_emotion = self._calculate_overall_emotion(user_emotions)
            overall_agent_emotion = self._calculate_overall_emotion(agent_emotions)
            
            return {
                "user_emotion": overall_user_emotion,
                "agent_emotion": overall_agent_emotion,
                "user_messages_count": len(user_messages),
                "agent_messages_count": len(agent_messages),
                "detailed_emotions": {
                    "user": user_emotions,
                    "agent": agent_emotions
                },
                "emotion_trend": self._analyze_emotion_trend(user_emotions)
            }
            
        except Exception as e:
            logger.error(f"聊天记录情绪分析失败: {e}")
            return {"error": str(e)}

    def _clean_text(self, text: str) -> str:
        """清理文本，移除特殊字符和多余空格"""
        if not text:
            return ""
        
        # 移除时间戳格式 [时间]
        text = re.sub(r'\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\]', '', text)
        # 移除角色标识 [用户]、[智能体]
        text = re.sub(r'\[(用户|智能体)\]', '', text)
        # 移除方向标识 >>、<<
        text = re.sub(r'[<>]+', '', text)
        # 移除多余空格和换行
        text = re.sub(r'\s+', ' ', text).strip()
        
        return text

    def _calculate_overall_emotion(self, emotions: List[Dict]) -> Dict[str, any]:
        """计算整体情绪"""
        if not emotions:
            return {"emotion": "neutral", "confidence": 0.0}
        
        emotion_counts = {"positive": 0, "negative": 0, "neutral": 0}
        total_confidence = 0
        
        for emotion_data in emotions:
            emotion = emotion_data.get("emotion", "neutral")
            confidence = emotion_data.get("confidence", 0)
            
            if emotion in emotion_counts:
                emotion_counts[emotion] += confidence
                total_confidence += confidence
        
        if total_confidence == 0:
            return {"emotion": "neutral", "confidence": 0.0}
        
        # 归一化
        for emotion in emotion_counts:
            emotion_counts[emotion] = emotion_counts[emotion] / total_confidence
        
        main_emotion = max(emotion_counts, key=emotion_counts.get)
        
        return {
            "emotion": main_emotion,
            "confidence": emotion_counts[main_emotion],
            "distribution": emotion_counts
        }

    def _analyze_emotion_trend(self, emotions: List[Dict]) -> Dict[str, any]:
        """分析情绪趋势"""
        if len(emotions) < 2:
            return {"trend": "stable", "change": 0}
        
        # 计算前半段和后半段的平均情绪
        mid_point = len(emotions) // 2
        first_half = emotions[:mid_point]
        second_half = emotions[mid_point:]
        
        first_avg = self._calculate_overall_emotion(first_half)
        second_avg = self._calculate_overall_emotion(second_half)
        
        # 情绪变化趋势
        emotion_values = {"positive": 1, "neutral": 0, "negative": -1}
        
        first_value = emotion_values.get(first_avg["emotion"], 0) * first_avg["confidence"]
        second_value = emotion_values.get(second_avg["emotion"], 0) * second_avg["confidence"]
        
        change = second_value - first_value
        
        if change > 0.2:
            trend = "improving"
        elif change < -0.2:
            trend = "declining"
        else:
            trend = "stable"
        
        return {
            "trend": trend,
            "change": change,
            "first_half": first_avg,
            "second_half": second_avg
        }

# 全局实例
emotion_analyzer = EmotionAnalyzer()
